﻿#include "MyClass.h"
#include "PybindLinkedLibExport.h"
#include "pybind11/pybind11.h"
#include "pybind11/stl.h"

// 加入注释,不检查多线程锁
// pybind11::gil_scoped_acquire guard{};
#define PYBIND11_NO_ASSERT_GIL_HELD_INCREF_DECREF

// 最简单的相加函数
int add(int i, int j) {
  return i + j;
}

void* addPtr(int* i, int* j) {
  auto v = new int{};
  *v = *i + *j;
  return v;
}

int usePtr(void* arg) {
  auto p{(int*) arg};
  return *p;
}

std::string theStr(char* arg) {
  return std::string{arg};
}

/******** 回调函数 ********/
// 函数接受一个回调函数作为参数
int add_callback(int x, int y, const std::string& str,
                 const pybind11::function& callback) {
  // 多线程时必须要此指令,让python的object在此可以检索,否则会直接崩溃
  pybind11::gil_scoped_acquire guard{};
  // 调用回调函数
  int result = callback(x, y, str).cast<int>();
  return result;
}

// 接收一个回调函数用来处理字符串数组
void nodeInfoUpdate(const std::vector<std::string>& arg,
                    const pybind11::function& callback) {
  // 调用回调函数
  callback(arg);
}

// 这里会设置模型名字,这里的名字为Pybind11Lib,
// 必须和CMakeLists.txt中的pybind11_add_module定义的名字一样
PYBIND11_MODULE(Pybind11Lib, m) {
  m.doc() = "pybind11 add example plugin";
  m.def("add", &add, "orginal add two numbers function");
  m.def("add_lambda", [](int i, int j) { return i + j; }, "Adds two numbers");
  m.def("add_callback", &add_callback, "add callback function");
  m.def("addPtr", &addPtr, "add two num ptr");
  m.def("usePtr", &usePtr, "use ptr");
  m.def("theStr", &theStr, "use string");
  m.def("nodeInfoUpdate", &nodeInfoUpdate, "use string array");

  m.def("sub", &sub, "other lib sub function");

  pybind11::class_<MyClass, std::shared_ptr<MyClass>>(m, "MyClass")
      .def(pybind11::init<>())
      .def("add", &MyClass::add, "two value operator");
}